#ifndef EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD
#define EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD

// This code comes from:
// https://github.com/dhbaird/easywsclient
//
// To get the latest version:
// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.hpp
// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.cpp

#include <string>
#include <vector>

namespace easywsclient {

struct Callback_Imp {
  virtual void operator()(const std::string& message) = 0;
};
struct BytesCallback_Imp {
  virtual void operator()(const std::vector<uint8_t>& message) = 0;
};

class WebSocket {
 public:
  typedef WebSocket* pointer;
  typedef enum readyStateValues { CLOSING, CLOSED, CONNECTING, OPEN } readyStateValues;

  // Factories:
  static pointer create_dummy();
  static pointer from_url(const std::string& url, const std::string& origin = std::string());
  static pointer from_url_no_mask(const std::string& url, const std::string& origin = std::string());

  // Interfaces:
  virtual ~WebSocket() {}
  virtual void poll(int timeout = 0) = 0;  // timeout in milliseconds
  virtual void send(const std::string& message) = 0;
  virtual void sendBinary(const std::string& message) = 0;
  virtual void sendBinary(const std::vector<uint8_t>& message) = 0;
  virtual void sendPing() = 0;
  virtual void close() = 0;
  virtual readyStateValues getReadyState() const = 0;

  template <class Callable>
  void dispatch(Callable callable)
  // For callbacks that accept a string argument.
  {  // N.B. this is compatible with both C++11 lambdas, functors and C function pointers
    struct _Callback : public Callback_Imp {
      Callable& callable;
      _Callback(Callable& callable) : callable(callable) {}
      void operator()(const std::string& message) { callable(message); }
    };
    _Callback callback(callable);
    _dispatch(callback);
  }

  template <class Callable>
  void dispatchBinary(Callable callable)
  // For callbacks that accept a std::vector<uint8_t> argument.
  {  // N.B. this is compatible with both C++11 lambdas, functors and C function pointers
    struct _Callback : public BytesCallback_Imp {
      Callable& callable;
      _Callback(Callable& callable) : callable(callable) {}
      void operator()(const std::vector<uint8_t>& message) { callable(message); }
    };
    _Callback callback(callable);
    _dispatchBinary(callback);
  }

 protected:
  virtual void _dispatch(Callback_Imp& callable) = 0;
  virtual void _dispatchBinary(BytesCallback_Imp& callable) = 0;
};

}  // namespace easywsclient

#endif /* EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD */
